package com.leps.nq.common.util;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class DataUtils {
    final static Map<String, Integer> DATA_LENGTH_MAPPING = new HashMap<>();

    static {
        DATA_LENGTH_MAPPING.put("VB", 1);
        DATA_LENGTH_MAPPING.put("VW", 2);
        DATA_LENGTH_MAPPING.put("VD", 4);
        // ignore case
        DATA_LENGTH_MAPPING.put("vb", 1);
        DATA_LENGTH_MAPPING.put("vw", 2);
        DATA_LENGTH_MAPPING.put("vd", 4);
    }

    public static byte[] hexStrToBytes(String hexStr) {
        return HexUtil.decodeHex(hexStr);
    }

    public static String bytesToHexStr(byte[] data) {
        return HexUtil.format(HexUtil.encodeHexStr(data)).toUpperCase();
    }

    public static byte[] intToWord(int val) {
        byte[] bytes = NumberUtil.toBytes(val);
        byte[] word = new byte[2];
        // 高低字节互换
        word[0] = bytes[3];
        word[1] = bytes[2];
        return word;
    }

    public static int wordToInt(byte[] word) {
        // 高低字节互换并补2个字节到高位
        byte[] data = new byte[]{0, 0, word[1], word[0]};
        return NumberUtil.toInt(data);
    }

    public static byte[] intToDword(int val) {
        byte[] bytes = NumberUtil.toBytes(val);
        byte[] dword = new byte[4];
        // 高低字节互换
        dword[0] = bytes[3];
        dword[1] = bytes[2];
        dword[2] = bytes[1];
        dword[3] = bytes[0];
        return dword;
    }

    private static double dwordToDouble(byte[] dword) {
        // 前2个字节和后2个字节地址互换并补充4字节
        byte[] data = new byte[]{0, 0, 0, 0, dword[2], dword[3], dword[0], dword[1]};
        // 转换为long
        long longBits =
                ((long) data[0] << 56) +
                        ((long) (data[1] & 255) << 48) +
                        ((long) (data[2] & 255) << 40) +
                        ((long) (data[3] & 255) << 32) +
                        ((long) (data[4] & 255) << 24) +
                        ((data[5] & 255) << 16) +
                        ((data[6] & 255) << 8) +
                        ((data[7] & 255) << 0);
        return Double.longBitsToDouble(longBits);
    }

    public static byte[] getDataValue(Integer firstAddress, Integer dataAddress, String dataType, byte[] datagram) {
        int len = 2;
        if (StrUtil.isNotEmpty(dataType))
            len = DATA_LENGTH_MAPPING.get(dataType);
        int index = dataAddress - firstAddress;
        return Arrays.copyOfRange(datagram, index, index + len);
    }

    public static int getDataValueAsInt(Integer firstAddress, Integer dataAddress, String dataType, byte[] datagram) {
        byte[] b = getDataValue(firstAddress, dataAddress, dataType, datagram);
        if ("VB".equalsIgnoreCase(dataType)) {
            return b[0];
        } else if ("VW".equalsIgnoreCase(dataType)) {
            return wordToInt(b);
        }
        return 0;
    }

    public static double getDataValueAsDouble(Integer firstAddress, Integer dataAddress, String dataType, byte[] datagram) {
        byte[] b = getDataValue(firstAddress, dataAddress, dataType, datagram);
        if ("VB".equalsIgnoreCase(dataType)) {
            return b[0];
        } else if ("VW".equalsIgnoreCase(dataType)) {
            return wordToInt(b);
        } else if ("VD".equalsIgnoreCase(dataType)) {
            return dwordToDouble(b);
        }
        return 0;
    }

    public static Object getDataValueAsObject(Integer firstAddress, Integer dataAddress, String dataType, byte[] datagram) {
        byte[] b = getDataValue(firstAddress, dataAddress, dataType, datagram);
        if ("VB".equalsIgnoreCase(dataType)) {
            return b[0];
        } else if ("VW".equalsIgnoreCase(dataType)) {
            return wordToInt(b);
        } else if ("VD".equalsIgnoreCase(dataType)) {
            return dwordToDouble(b);
        }
        return 0;
    }

}
